<html>
<head>
    <link type="text/css" rel="stylesheet" href="http://s.codeproject.com/App_Themes/CodeProject/Css/Main.min.css?dt=2.8.140501.1" />
</head>

<body>
<!-- Article Starts -->

<ul class="download">
    <li><a href="http://sourceforge.net/projects/sharppcap/">Download SharpPcap source code and examples or binaries</a></li>
    <li><a href="http://sourceforge.net/apps/mediawiki/sharppcap/index.php">Check out the SharpPcap home packet page</a></li>
</ul>

<p><img height=279 src="sharppcap/SharpPcap.png" width=600></p>
<p><small>[A .NET sniffer application written with SharpPcap]</small></p>


<h2>Introduction</h2>
<p>Packet capturing (or packet sniffing) is the process of collecting all packets of data that pass through a given network interface. Capturing network packets in our applications is a powerful capability which lets us write network monitoring, packet analyzers and security tools. The <a href="http://www.tcpdump.org/" target="_blank">libpcap</a> library for UNIX based systems and <a href="http://www.winpcap.org/" target="_blank">WinPcap</a> for Windows are the most widely used packet capture drivers that provide API for low-level network monitoring. Among the applications that use libpcap/WinPcap as its packet capture subsystem are the famous <a href="http://www.tcpdump.org/" target="_blank">tcpdump</a> and <a href="http://www.wireshark.org/" target="_blank">Wireshark</a>.</p>
<p>In this article, we will introduce the <a href="http://sourceforge.net/projects/sharppcap" target="_blank">SharpPcap</a> .NET assembly (library) for interfacing with libpcap or winpcap from your .NET application and will give you a detailed programming tutorial on how to use it.</p>


<h2>Background</h2>
<p>Tamir Gal started the SharpPcap project around 2004. He wanted to use WinPcap in a .NET application while working on his final project for university. The project involved analyzing and decoding VoIP traffic and he wanted to keep coding simple with C# which has time saving features like garbage collection. Accessing the WinPcap API from .NET seemed to be quite a popular requirement, and he found some useful projects on CodeProject's website that let you do just that.</p>
<p>The projects available at the time did not lend themselves to being used to capture and analyze traffic. Some had mixed ui and capture code, others had reimplemented some of WinPcap's functions in C# and others lacked features such as offline file reading or source code.</p>
<p>And so, Tamir decided to start his own library for the task. Several versions in the 1.x series were released. Development slowed towards mid-2007 when the last version in the 1.x series was released, SharpPcap 1.6.2.</p>
<p>Chris Morgan took over development of SharpPcap in November of 2008. Since then SharpPcap has had major internal rewrites and API improvements including Linux, Mac support.</p>
<p>In late February 2010 SharpPcap v3.0 was released. This release represents a rewrite of SharpPcap's packet parsers. Packet parsing functionality was broken out into a new library, <a href="http://packetnet.sf.net">Packet.Net</a>. SharpPcap takes care of interfacing with libpcap/winpcap and Packet.Net takes care of packet dissection and creation. The details of Packet.Net's architecture will be discussed later in the turotial.</p>
<p>SharpPcap v3.5 was released February 1st, 2011. The 3.5 release contained significant API changes as well as WinPcap remote capture and AirPcap support.</p>
<p>SharpPcap v4.0 was released September 13, 2011. The 4.0 release contains significant performance improvements due to contributions from Michael Giagnocavo. SharpPcap 4.0 is >50% faster than the last revision, v3.7. It also contains API cleanup for reading and writing to capture files in the form of new CaptureFileWriterDevice and CaptureFileReaderDevice that replaces an older and much more confusing way of writing to capture files and makes reading and writing analogous.
<p>SharpPcap v4.2 was released January 14th, 2013. 4.2 adds support for IEEE 802.1Q vlan tags, corrects access modifiers in Packet to enable 3rd party assemblies to use this class and introduces Packet.Extract(). Packet.Extract() replaces per-packet GetEncapsulated() methods, now deprecated, with a single high level routine that is a part of the base class of all captured packets.

<h2>About SharpPcap</h2>
<p>The purpose of <a href="http://sourceforge.net/projects/sharppcap" target="_blank">SharpPcap</a> is to provide a framework for capturing, injecting and analyzing network packets for .NET applications.</p>
<p>SharpPcap is openly and actively developed with its source code and file releases hosted on SourceForge. Source code patches to improve or fix issues are welcome via the <a href="http://lists.sourceforge.net/lists/listinfo/sharppcap-devel">sharppcap developers mailing list</a>. Bug reports, feature requests and other queries are actively answered on the support forums and issue trackers there so if you have any trouble with the library please feel free to ask.</p>
<p>SharpPcap is a fully managed cross platform library. The same assembly runs under Microsoft .NET as well as <a href="http://mono-project.com">Mono</a> on both 32 and 64bit platforms.</p>
<p>The following list illustrates the features currently supported by SharpPcap:</p>
<ul>
    <li><b>Single assembly</b> for <b>Microsoft .NET</b> and <b>Mono</b> platforms on <i>Windows (32 or 64bit)</i>, <i>Linux (32 or 64bit)</i> and <i>Mac</i>.</li>
    <li>High performance - SharpPcap can capture fast enough to keep up with >3MB/s scp transfer rates</li>
    <li><a href="http://www.winpcap.org/docs/docs_412/index.html">WinPcap</a> extensions are partially supported:
        <ul>
            <li>Remote packet capture</li>
            <li>Setting the kernel buffer size</li>
            <li>Injecting packets using send queues.</li>
            <li>Collecting network statistics on a given network interface</li>
        </ul>
    </li>
    <li><a href="http://www.cacetech.com/products/airpcap.html">AirPcap</a> support</li>
    <li>Enumerating and showing details about the physical network interface on a Windows machine.</li>
    <li>Capturing low-level network packets going through a given interface.</li>
    <li><a href="http://packetnet.sf.net">Packet.Net</a> is used for packet parsing</li>
    <li>Injecting low-level network packets on a given interface.</li>
    <li>Handling (reading and writing) packet capture files.</li>
    <li>Retrieving adapter statistics on packets received vs. dropped</li>
</ul>

<b>Packet.Net</b> supports analyzing and parsing the following protocols:
   <i>
      <ul>
         <li><a href="http://en.wikipedia.org/wiki/Ethernet#Ethernet_frame_types_and_the_EtherType_field">Ethernet</a></li>
         <li><a href="http://wiki.wireshark.org/SLL">SLL (Linux Cooked-Mode Capture)</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Address_Resolution_Protocol">ARP (Address Resolution Protocol)</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Internet_Protocol">IP (Internet Protocol)</a>:
               <ul>
                  <li><a href="http://en.wikipedia.org/wiki/IPv4">IPv4</a></li>
                  <li><a href="http://en.wikipedia.org/wiki/IPv6">IPv6</a></li>
               </ul>
         </li>
         <li><a href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP (Transmission Control Protocol)</a></li>
         <li><a href="http://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP (User Datagram Protocol)</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol">ICMP (Internet Control Message Protocol)</a>:
               <ul>
                  <li><a href="http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol">ICMPv4</a></li>
                  <li><a href="http://en.wikipedia.org/wiki/ICMPv6">ICMPv6</a></li>
               </ul>
         </li>
         <li><a href="http://en.wikipedia.org/wiki/IGMP">IGMPv2</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Pppoe">PPPoE</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Point-to-Point_Protoco">PTP</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Link_Layer_Discovery_Protocol">LLDP</a></li>
         <li><a href="http://http://en.wikipedia.org/wiki/Wake-on-LAN">Wake-on-LAN(WOL)</a></li>
         <li><a href="http://en.wikipedia.org/wiki/IEEE_802.1Q">IEEE 802.1Q</a></li>
      </ul>
   </i>
<p>Please check the project homepage <a href="http://sourceforge.net/projects/sharppcap" target="_blank">homepage</a> for the latest updates and bug fixes.</p>

<h2>SharpPcap architecture</h2>
<p>SharpPcap has a layered architecture, at the top level are classes that work across all devices:
<ul>
  <li><b>CaptureDeviceList</b> - Retrieves a list of all devices on the system</li>
  <li><b>ICaptureDevice</b> - All capture devices have ICaptureDevice interfaces</li>
</ul>

The namespaces are layed out hierarchically:
<ul>
  <li><b>LibPcap</b>
    <ul>
      <li><b>LibPcapLiveDevice</b> - A ICaptureDevice</li>
      <li><b>LibPcapLiveDeviceList</b> - Retrieves a list of <i>LibPcapLiveDevice</i> devices (these include pcap/winpcap and airpcap devices)</li>
      <li><b>CaptureFileReaderDevice</b> - Device that reads from a pcap capture file</li>
      <li><b>CaptureFileWriterDevice</b> - Device that creates or writes to a pcap format capture file</li>
    </ul>
  </li>
  <li><b>WinPcap</b>
    <ul>
      <li><b>WinPcapDeviceList</b> - Retrieves a list of <i>WinPcapDevice</i>s (these include winpcap and airpcap devices)</li>
      <li><b>WinPcapDevice</b> - A LibPcapLiveDevice with additional WinPcap features and interfaces</li>
    </ul>
  </li>
  <li><b>AirPcap</b>
    <ul>
      <li><b>AirPcapDeviceList</b> - Retrives a list of <i>AirPcapDevice</i>s</li>
      <li><b>AirPcapDevice</b> - A WinPcapDevice with additional AirPcap features and interfaces</li>
    </ul>
  </li>
</ul>

CaptureDeviceList returns a list of fully differentiated devices. This means that each ICaptureDevice returned by CaptureDeviceList is either a LibPcapLiveDevice, a WinPcapDevice or a AirPcapDevice. This allows you to retrieve the entire list of devices and differentiate by looking at the type of each device. If you would like to get a specific type of device only you can use one of the particular *DeviceList classes.

<pre lang="cs">
<span class="code-comment">// Retrieve all capture devices</span>
var devices = CaptureDeviceList.Instance;

<span class="code-comment">// differentiate based upon types</span>
foreach(ICaptureDevice dev in devices)
{
  if(dev is AirPcapDevice)
  {
    <span class="code-comment">// process as an AirPcapDevice</span>
  } else if(dev is WinPcapDevice)
  {
    <span class="code-comment">// process as an WinPcapDevice</span>
  } else if(dev is LibPcapLiveDevice)
  {
    <span class="code-comment">// process as an LibPcapLiveDevice</span>
  }
}
</pre>

<pre lang="cs">
<span class="code-comment">// Retrieve only WinPcap (and AirPcap devices)</span>
var devices = AirPcapDeviceList.Instance;
foreach(AirPcapDevice dev in devices)
{
  <span class="code-comment">// Process this AirPcap device</span>
}
</pre>

</p>


<h2>Packet.Net architecture and usage</h2>
<p>Packet.Net switched from the inheritance model of SharpPcap 2.x to one of nesting packets. Avoiding inheritance makes Packet.Net more flexible and simplifies the construction of complex packets. While the inheritance model made some things easier, a UdpPacket for instance had a SourceHwAddress (the parent Ethernet packet's source mac address field), it also made things very difficult. What about Ethernet packets that were themselves inside of other packets? When a udp packet was created do I need to specify all of its fields and the fields of all of its parents? The nesting approach solves these problems by separating the different packet layers, and things like Packet.Extract(), discussed further on, make it easy to retrieve sub-packets.
<p>All packets contain a Packet PayloadPacket property and a Byte[] PayloadData property. One or neither of these can be valid. A Tcp packet captured on Ethernet may be EthernetPacket -> IPv4 Packet -> Tcp Packet. In Packet.Net the Tcp packet could be accessed like capturedPacket.PayloadPacket.PayloadPacket but to to aid users <code>Packet.Extract(System.Type type)</code> was created so you can do <code>TcpPacket tcpPacket = (TcpPacket)capturedPacket.Extract(typeof(TcpPacket));</code>.</p>
<p>The Packet.Extract() is a uniform method that, when given a type, will retrieve the nested packet of that given type. If 'p' is a udp packet, then (UdpPacket)p.Extract(typeof(UdpPacket) will return the Udp packet of a packet that consists of EthernetPacket -> IP packet -> UdpPacket or Linux Cooked Capture -> IP -> UdpPacket or an EthernetPacket -> PPPoE -> PTP -> IP -> UdpPacket. We recommend using the Packet.Extact() approach rather than the older and now deprecated GetEncapsulated() methods, or other more manual approaches.</p>
<p>With Packet.Net constructing packets looks like:
<pre lang="cs">
<span class="code-keyword">using</span> PacketDotNet;

<span class="code-keyword">ushort</span> tcpSourcePort = <span class="code-digit">123</span>;
<span class="code-keyword">ushort</span> tcpDestinationPort = <span class="code-digit">321</span>;
<span class="code-SDKkeyword">var</span> tcpPacket = <span class="code-keyword">new</span> <span class="code-SDKkeyword">TcpPacket</span>(tcpSourcePort, tcpDestinationPort);

<span class="code-SDKkeyword">var</span> ipSourceAddress = System.Net.IPAddress.Parse(<span class="code-string">&quot;192.168.1.1&quot;</span>);
<span class="code-SDKkeyword">var</span> ipDestinationAddress = System.Net.IPAddress.Parse(<span class="code-string">&quot;192.168.1.2&quot;</span>);
<span class="code-SDKkeyword">var</span> ipPacket = <span class="code-keyword">new</span> <span class="code-SDKkeyword">IPv4Packet</span>(ipSourceAddress, ipDestinationAddress);

<span class="code-SDKkeyword">var</span> sourceHwAddress = <span class="code-string">&quot;90-90-90-90-90-90&quot;</span>;
<span class="code-SDKkeyword">var</span> ethernetSourceHwAddress = System.Net.NetworkInformation.PhysicalAddress.Parse(sourceHwAddress);
<span class="code-SDKkeyword">var</span> destinationHwAddress = <span class="code-string">&quot;80-80-80-80-80-80&quot;</span>;
<span class="code-SDKkeyword">var</span> ethernetDestinationHwAddress = System.Net.NetworkInformation.PhysicalAddress.Parse(destinationHwAddress);

<span class="code-comment">// NOTE: using EthernetPacketType.None to illustrate that the Ethernet
//       protocol type is updated based on the packet payload that is
//       assigned to that particular Ethernet packet</span>
<span class="code-SDKkeyword">var</span> ethernetPacket = <span class="code-keyword">new</span> <span class="code-SDKkeyword">EthernetPacket</span>(ethernetSourceHwAddress,
    ethernetDestinationHwAddress,
    EthernetPacketType.None);

<span class="code-comment">// Now stitch all of the packets together</span>
ipPacket.PayloadPacket = tcpPacket;
ethernetPacket.PayloadPacket = ipPacket;

<span class="code-comment">// and print out the packet to see that it looks just like we wanted it to</span>
Console.WriteLine(ethernetPacket.ToString());

<span class="code-comment">// to retrieve the bytes that represent this newly created EthernetPacket use the Bytes property</span>
byte[] packetBytes = ethernetPacket.Bytes;
</pre>
</p>


<h2>SharpPcap tutorial: A step by step guide to using SharpPcap</h2>
<p>These and many other examples can be found in the Examples/ directory of the source package. Go to the <a href="https://sourceforge.net/projects/sharppcap/files/SharpPcap/">SharpPcap files page</a>, select the release directory you want and download the package named like <i>SharpPcap-X.Y.Z.src.zip</i>.</p>
<p>The text of this tutorial was taken directly from WinPcap's <a href="http://www.winpcap.org/docs/docs_41b5/html/group__wpcap__tut.html" target="_blank">official tutorial</a> but is modified to show the C# use of the SharpPcap library. All examples can be downloaded together with the SharpPcap source code from the top of this page. If you are running on Windows, the WinPcap library must be installed before attempting to run any of these examples so please download and install the latest version from <a href="http://www.winpcap.org/install/default.htm" target="_blank">WinPcap's download page</a>. If running under unix/linux/mac the libpcap library must be installed using your systems software management system.</p>
<p>The following topics are covered in this tutorial with the name of the example in parenthesis:</p>
<ol>
    <li><a href="#ifList">Obtaining the device list (Example 1)</a></li>
    <li><a href="#basicCap">Opening an adapter and capturing packets (Example 3)</a></li>
    <li><a href="#basicCapNoCallback">Capturing packets without the event  (Example 4)</a></li>
    <li><a href="#filter">Filtering the traffic (Example 5)</a></li>
    <li><a href="#writeToFile">Writing packets to a capture file (CreatingCaptureFile)</a></li>
    <li><a href="#readFromFile">Reading packets from a capture file (ReadingCaptureFile)</a></li>
    <li><a href="#dumpTCP">Interpreting the packets (Example 6)</a></li>
    <li><a href="#sendPackets">Sending packets (Example 9)</a></li>
    <li><a href="#sendqueues">Send Queues (Example 10) - WinPcap only</a></li>
    <li><a href="#statistics">Gathering statistics on the network traffic (Example 11) - WinPcap only</a></li>
    <li><a href="#QueuingPacketsForBackgroundProcessing">Queuing packets for background processing - High packet rate capture</a></li>
</ol>


<h3 id=ifList>Obtaining the device list (Example 1 in the source package)</h3>
<p>Typically, the first thing that a SharpPcap-based application does is get a list of attached network adapters. SharpPcap provides a class, <code>CaptureDeviceList</code> for this purpose. The class is a singleton instance that holds a cached list of network adapters of type <code>ICaptureDevice</code>. In particular, the <code>Name</code> and <code>Description</code> properties contain the name and a human readable description, respectively, of the corresponding device. The following C# sample shows how to retrieve a list of adapters and print it on the screen, printing an error if no adapters are found:</p>
<pre lang="cs">
<span class="code-comment">// Print SharpPcap version</span> 
<span class="code-keyword">string</span> ver = SharpPcap.Version.VersionString;
Console.WriteLine(<span class="code-string">&quot;SharpPcap {0}, Example1.IfList.cs&quot;</span>, ver);

<span class="code-comment">// Retrieve the device list</span>
<span class="code-SDKkeyword">CaptureDeviceList</span> devices = CaptureDeviceList.Instance;

<span class="code-comment">// If no devices were found print an error</span>
<span class="code-keyword">if</span>(devices.Count &lt; <span class="code-digit">1</span>)
{
    Console.WriteLine(<span class="code-string">&quot;No devices were found on this machine&quot;</span>);
    <span class="code-keyword">return</span>;
}

Console.WriteLine(<span class="code-string">&quot;\nThe following devices are available on this machine:&quot;</span>);
Console.WriteLine(<span class="code-string">&quot;----------------------------------------------------\n&quot;</span>);

<span class="code-comment">// Print out the available network devices</span>
<span class="code-keyword">foreach</span>(<span class="code-SDKkeyword">ICaptureDevice</span> dev <span class="code-keyword">in</span> devices)
    Console.WriteLine(<span class="code-string">&quot;{0}\n&quot;</span>, dev.ToString());

Console.Write(<span class="code-string">&quot;Hit 'Enter' to exit...&quot;</span>);
Console.ReadLine();
</pre>
<p>The output of the above application will be as something like this:</p>
<pre>
c:\sharppcap\Examples\Example1.IfList\bin\Debug>Example1.IfList.exe
SharpPcap 3.5.0.0, Example1.IfList.cs

The following devices are available on this machine:
----------------------------------------------------

interface: Name: \Device\NPF_{D8B7C9B2-D53D-45DA-ACF0-2E2116F97314}
FriendlyName: Local Area Connection 2
Description: Intel(R) PRO/1000 MT Desktop Adapter
Addresses:
Addr:      fe80::b444:92d8:c882:8227
Netmask:
Broadaddr:

Addresses:
Addr:      10.0.2.15
Netmask:   255.255.255.0
Broadaddr: 255.255.255.255

Addresses:
Addr:      HW addr: 0800276AC792

Flags: 0

Hit 'Enter' to exit...
</pre>


<h3 id=basicCap>Opening an adapter and capturing packets (Example 3 in the source package)</h3>
<p>Now that we've seen how to obtain an adapter to play with, let's start the real job, opening an adapter and capturing some traffic. In this section, we'll write a program that prints some information about each packet flowing through the adapter.</p>
<p>The function that opens a device for capture is <code>Open()</code> which is overloaded with some arguments as follows:</p>
<ul class=method>
    <li><code>Open()</code>
    <li><code>Open(<span class="code-keyword">DeviceMode</span> mode)</code>
    <li><code>Open(<span class="code-keyword">DeviceMode</span> mode, <span class="code-keyword">int</span> read_timeout)</code></li>
</ul>
<p>The above two arguments deserve some further explanation.</p>
<p><code>DeviceMode</code> In normal mode (<code>DeviceMode.Normal</code>), a network adapter only captures packets addressed directly to it; the packets exchanged by other hosts on the network are ignored. Instead, when the adapter is in promiscuous mode (<code>DeviceMode.Promiscuous</code>) it captures all packets whether they are destined to it or not. This means that on shared media (like non-switched Ethernet), libpcap/WinPcap will be able to capture the packets of other hosts. Promiscuous mode is the default for most capture applications, so we enable it in the following example. NOTE: Promiscuous mode can be detected via network means so if you are capturing in promiscuous mode you may be able to be detected by other entities on the network. Search for "detect promiscuous" via a web search engine for more information.</p>
<p><code>read_timeout</code>: Specifies the read timeout, in milliseconds. A read on the adapter (for example, using the <code>GetNextPacket()</code> function) will always return after <code>read_timeout</code> milliseconds, even if no packets are available from the network. <code>read_timeout</code> also defines the interval between statistical reports if the adapter is in statistical mode (see the <i><a href="#statistics">Gathering statistics on the network traffic</a></i> section). Setting <code>read_timeout</code> to 0 means no timeout, a read on the adapter never returns if no packets arrive. A -1 timeout on the other side causes a read on the adapter to always return immediately.</p>
<p>The following example shows the use of the <code>OnPacketArrival</code> event for receiving packets. We create an event handler that is being called whenever a new packet is going through the <code>ICaptureDevice</code>:</p>
<pre lang="cs">
<span class="code-comment">// Extract a device from the list</span>
<span class="code-SDKkeyword">ICaptureDevice</span> device = devices[i];

<span class="code-comment">// Register our handler function to the</span>
<span class="code-comment">// 'packet arrival' event</span>
device.OnPacketArrival +=
    <span class="code-keyword">new</span> <span class="code-SDKkeyword">SharpPcap.PacketArrivalEventHandler</span>(device_OnPacketArrival);

<span class="code-comment">// Open the device for capturing</span>
<span class="code-keyword">int</span> readTimeoutMilliseconds = <span class="code-digit">1000</span>;
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

Console.WriteLine(<span class="code-string">&quot;-- Listening on {0}, hit 'Enter' to stop...&quot;</span>,
    device.Description);

<span class="code-comment">// Start the capturing process</span>
device.StartCapture();

<span class="code-comment">// Wait for 'Enter' from the user.</span>
Console.ReadLine();

<span class="code-comment">// Stop the capturing process</span>
device.StopCapture();

<span class="code-comment">// Close the pcap device</span>
device.Close();
</pre>
<p>And here is our packet handler implementation:</p>
<pre lang="cs">
<span class="code-SummaryComment">/// &lt;summary&gt;
/// <span class="code-comment">Prints the time and length of each received packet</span>
/// &lt;/summary&gt;</span>
<span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-keyword">void</span> device_OnPacketArrival(<span class="code-keyword">object</span> sender, <span class="code-SDKkeyword">CaptureEventArgs</span> packet)
{
    <span class="code-SDKkeyword">DateTime</span> time = e.Packet.Timeval.Date;
    <span class="code-keyword">int</span> len = e.Packet.Data.Length;
    Console.WriteLine(<span class="code-string">&quot;</span><span class="code-string">{0}:{1}:{2},{3} Len={4}&quot;</span>,
        time.Hour, time.Minute, time.Second, time.Millisecond, len);
}
</pre>
<p>Once the adapter is opened, the capture can be started with the <code>StartCapture()</code> or <code>Capture(<span class="code-keyword">int</span> packetCount)</code> functions. These two functions are very similar, the difference is that <code>StartCapture()</code> is a non-blocking function that starts the capturing process on a new thread, while <code>Capture(<span class="code-keyword">int</span> packetCount)</code> blocks until <code>packetCount</code> packets have been captured. When using <code>StartCapture()</code> we should later call <code>StopCapture()</code> to terminate the capture process. To capture indefinitely call the <code>Capture()</code> method.</p>
<p>Both of these functions require that an event handler for processing packets registered prior to calling them. This event handler is invoked by <code>ICaptureDevice</code> for every new packet coming from the network and receives the sender object that invoked this handler (i.e. the <code>ICaptureDevice</code> object) and the actual received <code>Packet</code>, including all the protocol headers. Note that the frame CRC is normally not present in the packet, because it is removed by the network adapter after the frame validation. Note also that most adapters discard packets with wrong CRCs, so WinPcap (and therefore SharpPcap) is normally not able to capture them.</p>
<p>The <code>Packet</code> class represents a generic packet captured from the network. Each such packet has a <code>PcapHeader</code> property containing some info (e.g. the timestamp of the capture and the length of the packet) about the captured packet. The above example extracts the timestamp and the length from every <code>Packet</code> object and prints them on the screen.</p>
<p>Please note that the handler code is called by the <code>ICaptureDevice</code>; therefore the user application does not have direct control over it. Another approach is to use the <code>GetNextPacket()</code> function, which is presented in the next section.</p>


<h3 id=basicCapNoCallback>Capturing packets without the event handler (Example 4 in the source package)</h3>
<p>The example program in this section behaves exactly like the previous sample, but it uses <code>ICaptureDevice.GetNextPacket()</code> method instead of registering an event handler. The <code>OnPacketArrival</code> event is a good practice and could be a good choice in some situations, such as when capturing from several devices at once. However, handling a callback is sometimes not practical - it often makes the program more complex especially in situations with multithreaded applications. In these cases, <code>GetNextPacket()</code> retrieves a packet with a direct call - using <code>GetNextPacket()</code>, packets are received only when the programmer wants them. In the following program, we re-use the event handler code of the previous example and move it into a loop in the main function right after the call to <code>GetNextPacket()</code>.</p>
<p><b>Note</b>: The following example will exit if the timeout of 1000 ms expires with no packets on the network:</p>
<pre lang="cs">
<span class="code-comment">// Extract a device from the list</span>
<span class="code-SDKkeyword">ICaptureDevice</span> device = devices[i];

<span class="code-comment">// Open the device for capturing</span>
<span class="code-keyword">int</span> readTimeoutMilliseconds = <span class="code-digit">1000</span>;
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

Console.WriteLine();
Console.WriteLine(<span class="code-string">&quot;-- Listening on {0}...&quot;</span>,
    device.Description);

<span class="code-SDKkeyword">Packet</span> packet = <span class="code-keyword">null</span>;

<span class="code-comment">// Keep capture packets using GetNextPacket()</span>
<span class="code-keyword">while</span>((packet=device.GetNextPacket()) != <span class="code-keyword">null</span> )
{
    <span class="code-comment">// Prints the time and length of each received packet</span>
    <span class="code-SDKkeyword">DateTime</span> time = packet.PcapHeader.Date;
    <span class="code-keyword">int</span> len = packet.PcapHeader.PacketLength;
    Console.WriteLine(<span class="code-string">&quot;{0}:{1}:{2},{3} Len={4}&quot;</span>,
        time.Hour, time.Minute, time.Second,
        time.Millisecond, len);
}

<span class="code-comment">// Close the pcap device</span>
device.Close();
Console.WriteLine(<span class="code-string">&quot; -- Capture stopped, device closed.&quot;</span>);
</pre>


<h3 id=filter>Filtering the traffic (Example 5 in the source package)</h3>
<p>One of the most powerful features offered by libpcap and WinPcap is the filtering engine. It provides a very efficient way to receive subsets of the network traffic. WinPcap and libpcap have an integrated compiler that takes a string containing a high-level Boolean (filter) expression and produces a low-level byte code that can be interpreted by the filter engine of the packet capture driver. The syntax (also known as the <i>tcpdump syntax</i>) of the boolean expression is widely used in many applications other than WinPcap and libpcap. You can find its spec in WinPcap's <a href="http://www.winpcap.org/docs/docs_40_2/html/group__language.html" target="_blank">documentation page</a> or if you are running linux via 'man pcap-filter'.</p>
<p>The <code>Filter</code> property associates a filter with a capture adapter. Once <code>Filter</code> is set, the associated filter will be applied to all the packets coming from the network, and all the conformant packets (i.e., packets for which the boolean expression evaluates to true) will be actually copied to the application. The following code shows how to compile and set a filter.</p>
<p>Note that libpcap/winpcap's expression compiler requires that the netmask of the <code>ICaptureDevice</code> to be passed together with the filter, because some filters created by the compiler require it. However SharpPcap takes care of it for us by automatically extracting the netmask from the adapter.</p>
<p>The filter expression we use in the following snippet is "ip and tcp", which means to "keep only the packets that are both IPv4 and TCP and deliver them to the application":</p>
<pre lang="cs">
<span class="code-comment">// Open the device for capturing</span>
<span class="code-keyword">int</span> readTimeoutMilliseconds = <span class="code-digit">1000</span>;
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

<span class="code-comment">// tcpdump filter to capture only TCP/IP packets</span>
<span class="code-keyword">string</span> filter = <span class="code-string">&quot;ip and tcp&quot;</span>;
device.Filter = filter;

Console.WriteLine();
Console.WriteLine(<span class="code-string">&quot;-- The following tcpdump filter will be applied: \&quot;{0}\&quot;&quot;</span>,
    filter);
Console.WriteLine(<span class="code-string">&quot;-- Listening on {0}, hit 'Enter' to stop...&quot;</span>,
    device.Description);

<span class="code-comment">// Start capturing packets indefinitely</span>
device.Capture();

<span class="code-comment">// Close the pcap device</span>
<span class="code-comment">// (Note: this line will never be called since</span>
<span class="code-comment">// we're capturing indefinitely</span>
device.Close();
</pre>

<h3 id=writeToFile>Writing packets to a file (CreatingCaptureFile example in the source package)</h3>
<p>It is useful to be able to write captured packets to a file for offline processing, keeping records etc. Recently SharpPcap gained a new class for writing capture files, CaptureFileWriterDevice. In this example we will be capturing packets from a network device and writing
them to a newly created capture file.</p>
<p>
To write packets to a capture file create a CaptureFileWriterDevice. In this case we are creating one using the settings from
capture device called 'device'. Capture files need to know the link layer type, a <span class="code-keyword">PacketDotNet.LinkLayers</span>, and the capture packet length. CaptureFileWriterDevice will determine these if given an existing capture device of type
<span class="code-keyword">LibPcap.LibPcapLiveDevice</span>, or there are other constructors that take them as parameters.
</p>
<pre lang="cs">
<span class="code-comment">// open the output file</span>
captureFileWriter = <span class="code-keyword">new</span> CaptureFileWriterDevice(device, capFile);
</pre>
<p>Now that the captureFileWriter exists we can look at the OnPacketArrival handler to see how simple it is to write them to disk:</p>
<pre lang="cs">
<span class="code-comment">// write the packet to the file</span>
captureFileWriter.Write(e.Packet);
Console.WriteLine(<span class="code-string">&quot;Packet dumped to file.&quot;</span>);
</pre>

<h3 id=readFromFile>Reading packets from a file (ReadingCaptureFile example in the source package)</h3>
<p>Reading packets from a capture file is also quite simple. Create an instance of CaptureFileReaderDevice(string captureFilename)
and read packets as you would from any device. The ReadingCaptureFile example sets this up like:</p>
<pre lang="cs">
<span class="code-comment">// Register our handler function to the 'packet arrival' event</span>
device.OnPacketArrival +=
      <span class="code-keyword">new</span> PacketArrivalEventHandler( device_OnPacketArrival );

Console.WriteLine();
Console.WriteLine
      (<span class="code-string">&quot;-- Capturing from '{0}', hit 'Ctrl-C' to exit...&quot;</span>,
      capFile);

<span class="code-comment">// Start capture 'INFINTE' number of packets</span>
<span class="code-comment">// This method will return when EOF reached.</span>
device.Capture();
</pre>

<h3 id=dumpTCP>Interpreting the packets (Example 6 in the source package)</h3>
<p>Now that we are able to capture and filter network traffic, we want to put our knowledge to work with a simple "real world" application. In this lesson, we will take the code from the previous sections and use these pieces to build a more useful program. The main purpose of the current program is to show how the protocol headers of a captured packet can be parsed and interpreted. The resulting application, called DumpTCP, prints a summary of the TCP traffic on our network. I have chosen to parse and display the TCP protocol (rather than the UDP example posted in the original tutorial) because it is a bit more interesting than UDP and with SharpPcap it doesn't require too much parsing coding.</p>
<pre lang="cs">
<span class="code-SummaryComment">/// &lt;summary&gt;
/// <span class="code-comment">Prints the time, length, src ip,</span>
/// <span class="code-comment">src port, dst ip and dst port</span>
/// <span class="code-comment">for each TCP/IP packet received on the network</span>
/// &lt;/summary&gt;</span>
<span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-keyword">void</span> device_OnPacketArrival(
    <span class="code-keyword">object</span> sender, <span class="code-SDKkeyword">CaptureEventArgs</span> e)
{
    <span class="code-SDKkeyword">var</span> tcp = (TcpPacket)e.Packet.Extract(typeof(TcpPacket));
    <span class="code-keyword">if</span>(tcp != <span class="code-keyword">null</span>)
    {
        <span class="code-SDKkeyword">DateTime</span> time = e.Packet.Timeval.Date;
        <span class="code-keyword">int</span> len = e.Packet.Data.Length;
 
        <span class="code-keyword">string</span> srcIp = tcp.SourceAddress;
        <span class="code-keyword">string</span> dstIp = tcp.DestinationAddress;

        Console.WriteLine(<span class="code-string">&quot;</span><span class="code-string">{0}:{1}:{2},{3} Len={4}&quot;</span>,
            time.Hour, time.Minute, time.Second,
            time.Millisecond, len);
        Console.WriteLine(e.Packet.ToString());
    }
}</pre>
<p>If you take a look at the <a href="http://www.winpcap.org/docs/docs_41b5/html/group__wpcap__tut6.html" target="_blank">UDP example</a> of the original WinPcap tutorial you will see how complex it is to parse the packets (although UDP is a bit simpler to parse than TCP in our example) directly from the raw data bytes provided by the WinPcap library. Luckily for us, SharpPcap provides some useful packet analyzing classes for some common protocols (e.g. TCP, UDP, ICMP and others). These analyzing classes were initially a direct C# translation from <a href="http://jpcap.sourceforge.net/" target="_blank">JPcap</a>, a Java wrapper for libpcap/WinPcap similar to SharpPcap, but significant changes have been made to make them fit better into .NET. All of the packet parsing and generation code can be found in the <code>PacketDotNet</code> namespace in the PacketDotNet assembly.</p>
<P>As you can see, in our packet handler we first attempt to extract the Tcp packet encapsulated in the packet that was captured on the line. If one was found, and it should be since our filter selects only tcp packets, we can then access its properties. If we also wanted to see the IP packet properties these could be accessed via <code>var ip = (IpPacket)e.Packet.Extract(typeof(IpPacket));</code></p>
<pre>
Available devices:
------------------

1) Intel(R) PRO/1000 MT Mobile Connection
   (Microsoft's Packet Scheduler)

-- Please choose a device to capture: 1

-- Listening on Intel(R) PRO/1000 MT Mobile Connection
-- (Microsoft's Packet Scheduler)...
1:18:17,675 Len=123 66.102.7.147:80 -&gt; 10.21.98.21:43501
1:18:17,675 Len=80 10.21.98.21:43501 -&gt; 66.102.7.147:80
1:18:17,919 Len=54 66.102.7.147:80 -&gt; 10.21.98.21:43501
</pre>
<p>Each of the final three lines represents a different packet.</p>

<h3 id=sendPackets>Sending packets (Example 9 in the source package)</h3>
<p>The simplest way to send a packet is shown in the following code snippet. After opening an adapter, <code>SendPacket</code> is called to send a hand-crafted packet. <code>SendPacket</code> takes as argument a byte array or a <code>Packet</code> object containing the data to be sent. Notice that the buffer is sent to the network as it was received. This means that the application has to create the correct protocol headers in order to send something meaningful:</p>
<pre lang="cs">
<span class="code-comment">// Open the device</span>
device.Open();

<span class="code-comment">// Generate a random packet</span>
<span class="code-keyword">byte</span>[] bytes = GetRandomPacket();

<span class="code-keyword">try</span>
{
    <span class="code-comment">// Send the packet out the network device</span>
    device.SendPacket( bytes );
    Console.WriteLine(<span class="code-string">&quot;-- Packet sent successfuly.&quot;</span>);
}
<span class="code-keyword">catch</span>(<span class="code-SDKkeyword">Exception</span> e)
{
    Console.WriteLine(<span class="code-string">&quot;-- &quot;</span>+ e.Message );
}

<span class="code-comment">// Close the pcap device</span>
device.Close();
Console.WriteLine(<span class="code-string">&quot;-- Device closed.&quot;</span>);
</pre>


<h3 id=sendqueues>Send queues - WinPcap specific extension (Example 10 in the source package)</h3>
<p>While <code>SendPacket</code> offers a simple and immediate way to send a single packet, <b>send queues</b> provide an advanced, powerful and optimized mechanism to send a collection of packets. A send queue is a container for a variable number of packets that will be sent to the network. It has a size, that represents the maximum amount of bytes it can store.</p>
<p> Because SendQueue functionality is WinPcap specific the authors of SharpPcap recommend benchmarking your particular usage of sending packets to determine if the loss of cross platform support is worth the added efficiency of using send queues. The old adage, "avoid premature optimization" should be carefully considered.</p>
<p>SharpPcap represents a send queue using the <code>SendQueue</code> class which is constructed by specifying the size of the new send queue.</p>
<p>Once the send queue is created, <code>SendQueue.Add()</code> can be called to add a packet to the send queue. This function takes a <code>PcapHeader</code> with the packet's timestamp and length and a buffer or a <code>Packet</code> object holding the data of the packet. These parameters are the same as those received by the <code>OnPacketArrival</code> event, therefore queuing a packet that was just captured or a read from a file is a matter of passing these parameters to <code>SendQueue.Add()</code>.</p>
<p>To transmit a send queue, SharpPcap provides the <code>WinPcapDevice.SendQueue(SendQueue q, <span class="code-keyword">SendQueueTransmitModes</span> transmitMode)</code> function. Note the second parameter: if <code lang=cs><span class="code-keyword">SendQueueTransmitModes.Synchronized</span></code>, the send will be <i>synchronized</i>, i.e. the relative timestamps of the packets will be respected. This operation requires a remarkable amount of CPU, because the synchronization takes place in the kernel driver using "busy wait" loops. Although this operation is quite CPU intensive, it often results in very high precision packet transmissions (often around few microseconds or less).</p>
<p>Note that transmitting a send queue with <code>WinPcapDevice.SendQueue()</code> is more efficient than performing a series of <code>ICaptureDevice.SendPacket()</code>, since the send queue buffered at kernel level drastically decreases the number of context switches.</p>
<p>When a queue is no longer needed, it can be deleted with <code>SendQueue.Dispose()</code> that frees all the buffers associated with the send queue.</p>
<p>The next program shows how to use send queues. It opens a capture file by creating a <code>CaptureFileReaderDevice()</code>, then it stores the packets from the file to a properly allocated send queue. At his point it transmits the queue synchronized.</p>
<p>Note that the link-layer of the dumpfile is compared with one of the interface that will send the packets using the <code>PcapDevice.DataLink</code> property, and a warning is printed if they are different - it is important that the capture-file link-layer be the same as the adapter's link layer for otherwise the transmission is pointless:</p>
<pre lang="cs">
<span class="code-SDKkeyword">ICaptureDevice</span> device;

<span class="code-keyword">try</span>
{
    <span class="code-comment">// Create a CaptureFileReaderDevice</span>
    device = <span class="code-keyword">new</span> <span class="code-SDKkeyword">CaptureFileReaderDevice</span>(capFile);
    <span class="code-comment">// Open the device for capturing</span>
    device.Open();
}
<span class="code-keyword">catch</span>(<span class="code-SDKkeyword">Exception</span> e)
{
    Console.WriteLine(e.Message);
    <span class="code-keyword">return</span>;
}

Console.Write(<span class="code-string">&quot;Queuing packets...&quot;</span>);

<span class="code-comment">// Allocate a new send queue</span>
SendQueue squeue = <span class="code-keyword">new</span> <span class="code-SDKkeyword">SendQueue</span>
    ((<span class="code-keyword">int</span>)((<span class="code-SDKkeyword">CaptureFileReaderDevice</span>)device).FileSize);
<span class="code-SDKkeyword">Packet</span> packet;

<span class="code-keyword">try</span>
{
    <span class="code-comment">// Go through all packets in the file and add to the queue</span> 
    <span class="code-keyword">while</span>((packet=device.GetNextPacket()) != <span class="code-keyword">null</span> )
    {
        <span class="code-keyword">if</span>(!squeue.Add(packet))
        {
            Console.WriteLine(<span class="code-string">&quot;Warning: packet buffer too small, &quot;</span>+
                <span class="code-string">&quot;not all the packets will be sent.&quot;</span>);
            <span class="code-keyword">break</span>;
        }
    }
}
<span class="code-keyword">catch</span>(<span class="code-SDKkeyword">Exception</span> e)
{
    Console.WriteLine(e.Message);
    <span class="code-keyword">return</span>;
}

Console.WriteLine(<span class="code-string">&quot;OK&quot;</span>);

Console.WriteLine();
Console.WriteLine(<span class="code-string">&quot;The following devices are available on this machine:&quot;</span>);
Console.WriteLine(<span class="code-string">&quot;----------------------------------------------------&quot;</span>);
Console.WriteLine();

<span class="code-keyword">int</span> i=0;

<span class="code-SDKkeyword">var</span> devices = CaptureDeviceList.Instance;

<span class="code-comment">// Print out all available devices</span>
<span class="code-keyword">foreach</span>(<span class="code-SDKkeyword">ICaptureDevice</span> dev <span class="code-keyword">in</span> devices)
{
    Console.WriteLine(<span class="code-string">&quot;{0}) {1}&quot;</span>, i, dev.Description);
    i++;
}

Console.WriteLine();
Console.Write(<span class="code-string">&quot;-- Please choose a device to transmit on: &quot;</span>);
i = <span class="code-keyword">int</span>.Parse(Console.ReadLine());
devices[i].Open();
<span class="code-keyword">string</span> resp;
 
<span class="code-keyword">if</span>(devices[i].PcapDataLink != device.PcapDataLink)
{
    Console.Write(<span class="code-string">&quot;Warning: the datalink of the capture&quot;</span>+
        <span class="code-string">&quot;differs from the one of the selected interface,
        continue? [YES|no]&quot;</span>);
    resp = Console.ReadLine().ToLower();
 
    <span class="code-keyword">if</span>((resp!=<span class="code-string">&quot;&quot;</span>)&amp;&amp;(!resp.StartsWith(<span class="code-string">&quot;y&quot;</span>)))
    {
        Console.WriteLine(<span class="code-string">&quot;Canceled by user!&quot;</span>);
        devices[i].Close();
        <span class="code-keyword">return</span>;
    }
}

<span class="code-comment">// Close the device device</span>
device.Close();

<span class="code-comment">// find the network device for sending the packets we read</span>
device = devices[i];

Console.Write(<span class="code-string">&quot;This will transmit all queued packets through&quot;</span>+
    <span class="code-string">&quot;this device, continue? [YES|no]&quot;</span>);
resp = Console.ReadLine().ToLower();
 
<span class="code-keyword">if</span>((resp!=<span class="code-string">&quot;&quot;</span>)&amp;&amp;( !resp.StartsWith(<span class="code-string">&quot;y&quot;</span>)))
{
    Console.WriteLine(<span class="code-string">&quot;Canceled by user!&quot;</span>);
    <span class="code-keyword">return</span>;
}

<span class="code-keyword">try</span>
{
    Console.Write(<span class="code-string">&quot;Sending packets...&quot;</span>);
    <span class="code-keyword">int</span> sent = device.SendQueue(squeue, SendQueueTransmitModes.Synchronized);
    Console.WriteLine(<span class="code-string">&quot;Done!&quot;</span>);
    <span class="code-keyword">if</span>(sent &lt; squeue.CurrentLength)
    {
        Console.WriteLine(<span class="code-string">&quot;An error occurred sending the packets: {0}. &quot;</span>+
            <span class="code-string">&quot;Only {1} bytes were sent\n&quot;</span>, device.LastError, sent);
    }
}
<span class="code-keyword">catch</span>(<span class="code-SDKkeyword">Exception</span> e)
{
    Console.WriteLine(<span class="code-string">&quot;Error: &quot;</span>+e.Message );
}

<span class="code-comment">// Free the queue</span>
squeue.Dispose();
Console.WriteLine(<span class="code-string">&quot;-- Queue is disposed.&quot;</span>);

<span class="code-comment">// Close the pcap device</span>
device.Close();
Console.WriteLine(<span class="code-string">&quot;-- Device closed.&quot;</span>);
</pre>


<h3 id=statistics>Gathering statistics on the network traffic - WinPcap only (Example 11 in the source package)</h3>
<p>Adapter statistics are available by calling the ICaptureDevice.Statistics property. The Statistics property is supported by all ICaptureDevice types. WinPcap has a statistics extension that provides statistics callbacks that can be more efficient than retrieving device statistics over and over. WinPcap's statistical engine makes use of the kernel-level packet filter to efficiently classify the incoming packet. You can take a look at the <a href="http://www.winpcap.org/docs/docs_41b5/html/group__NPF.html" target="_blank">NPF driver internals manual</a> if you want to learn more about the details.</p>
<p>In order to use this feature, the programmer must open an adapter and put it in <i>statistical</i> mode. This can be done by setting the <code>PcapDevice.Mode</code> property. In particular, the <code>PcapDevice.Mode</code> property should be set to <code>CaptureMode.Statistics</code>.</p>
<p>With the statistical mode, making an application that monitors the TCP traffic load is a matter of few lines of code. The following sample shows how to do this:</p>
<pre lang="cs">
<span class="code-comment">// Register our handler function to the
// 'winpcap statistics' event</span>
device.OnPcapStatistics +=
    <span class="code-keyword">new</span> <span class="code-SDKkeyword">WinPcap.StatisticsModeEventHandler</span>(device_OnPcapStatistics);

<span class="code-comment">// Open the device for capturing</span>
<span class="code-keyword">int</span> readTimeoutMilliseconds = <span class="code-digit">1000</span>;
device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

<span class="code-comment">// Handle TCP packets only</span>
device.Filter = <span class="code-string">&quot;tcp&quot;</span>;

<span class="code-comment">// Set device to statistics mode</span>
device.Mode = CaptureMode.Statistics;

Console.WriteLine();
Console.WriteLine(<span class="code-string">&quot;-- Gathering statistics on \&quot;{0}\&quot;,
    hit 'Enter' to stop...&quot;</span>, device.Description);

<span class="code-comment">// Start the capturing process</span>
device.StartCapture();

<span class="code-comment">// Wait for 'Enter' from the user.</span>
Console.ReadLine();

<span class="code-comment">// Stop the capturing process</span>
device.StopCapture();

<span class="code-comment">// Close the pcap device</span>
device.Close();
Console.WriteLine(<span class="code-string">&quot;Capture stopped, device closed.&quot;</span>);
</pre>
<p>And our event handler will print the statistics:</p>
<pre lang="cs">
<span class="code-keyword">static</span> <span class="code-keyword">int</span> oldSec = <span class="code-digit">0</span>;
<span class="code-keyword">static</span> <span class="code-keyword">int</span> oldUsec = <span class="code-digit">0</span>;

<span class="code-SummaryComment">/// &lt;summary&gt;
/// <span class="code-comment">Gets a pcap stat object and calculate bps and pps</span>
/// &lt;/summary&gt;</span>
<span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-keyword">void</span> device_OnPcapStatistics(
             <span class="code-keyword">object</span> sender, <span class="code-SDKkeyword">StatisticsModeEventArgs</span> statistics)
{
    <span class="code-comment">// Calculate the delay in microseconds</span>
    <span class="code-comment">// from the last sample.</span>
    <span class="code-comment">// This value is obtained from the timestamp</span>
    <span class="code-comment">// that's associated with the sample.</span>
    <span class="code-keyword">int</span> delay = (statistics.Seconds - oldSec) *
        <span class="code-digit">1000000</span> - oldUsec + statistics.MicroSeconds;
    <span class="code-comment">/*</span><span class="code-comment"> Get the number of Bits per second */</span>
    <span class="code-keyword">long</span> bps = (statistics.RecievedBytes * <span class="code-digit">8</span> * <span class="code-digit">1000000</span>) / delay;
    <span class="code-comment">/*</span><span class="code-comment">                                  ^        ^
                                     |        |
                                     |        |
                                     |        |
            converts bytes in bits      -----         |
          delay is expressed in microseconds ---------
    */</span>

    <span class="code-comment">// Get the number of Packets per second</span>
    <span class="code-keyword">long</span> pps = (statistics.RecievedPackets * <span class="code-digit">1000000</span>) / delay;

    <span class="code-comment">// Convert the timestamp to readable format</span>
    <span class="code-keyword">string</span> ts = statistics.Date.ToLongTimeString();

    <span class="code-comment">// Print Statistics</span>
    Console.WriteLine(<span class="code-string">&quot;</span><span class="code-string">{0}: bps={1}, pps={2}&quot;</span>,
        ts, bps, pps);

    <span class="code-comment">// store current timestamp</span>
    oldSec = statistics.Seconds;
    oldUsec = statistics.MicroSeconds;
}
</pre>
<p>Note that this example is by far more efficient than a program that captures the packets in the traditional way and calculates statistics at the user-level. Statistical mode requires minimum amount of data copies and context switches and therefore the CPU is optimized. Moreover, a very small amount of memory is required. The downside is that if your application uses statistical mode it will only work with WinPcap on Windows.</p>


<h3 id=QueuingPacketsForBackgroundProcessing>Queuing packets for background processing - High packet rate capture (Example QueuingPacketsForBackgroundProcessing in the source package)</h3>
<p>Packet rates can exceed the rate at which they can be processed by the callback routines. This can occur if the packet processing code is time intensive, such as writing to disk, or if the packet processing code is performing advanced logic. Sometimes it is possible to reduce packet rates by applying bnf filters but in other cases these filters can be complex.</p>
<p>If packet rates only exceed the rate of processing for short periods of time it is possible to simply defer packet processing until periods of less activity. One technique for this is to queue the packets and process them in a background thread as shown in this example.</p>
<pre lang="cs">
<span class="code-keyword">using</span> System;
<span class="code-keyword">using</span> System.Collections.Generic;
<span class="code-keyword">using</span> SharpPcap;

<span class="code-keyword">namespace</span> <span class="code-SDKkeyword">QueuingPacketsForBackgroundProcessing</span>
{
    <span class="code-comment">/// <summary>
    /// Basic capture example showing simple queuing for background processing
    /// </summary></span>
    <span class="code-keyword">public class</span> MainClass
    {
        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">When true the background thread will terminate</span>
        /// &lt;/summary&gt;
        /// &lt;param name="args"&gt;
        /// <span class="code-comment">A &lt;see cref="System.String"/&gt;</span>
        /// &lt;/param&gt;</span>
        <span class="code-keyword">private static bool</span> BackgroundThreadStop = <span class="code-keyword">false</span>;

        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">Object that is used to prevent two threads from accessing</span>
        /// <span class="code-comment">PacketQueue at the same time</span>
        /// &lt;/summary&gt;
        /// &lt;param name="args"&gt;
        /// <span class="code-comment">A &lt;see cref="System.String"/&gt;</span>
        /// &lt;/param&gt;</span>
        <span class="code-keyword">private static object</span> QueueLock = <span class="code-keyword">new</span> <span class="code-SDKkeyword">object</span>();

        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">The queue that the callback thread puts packets in. Accessed by</span>
        /// <span class="code-comment">the background thread when QueueLock is held</span>
        /// &lt;/summary&gt;</span>
        <span class="code-keyword">private static</span> <span class="code-SDKkeyword">List</span><RawCapture> PacketQueue = <span class="code-keyword">new</span> <span class="code-SDKkeyword">List</span><RawCapture>();

        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">The last time PcapDevice.Statistics() was called on the active device.</span>
        /// <span class="code-comment">Allow periodic display of device statistics</span>
        /// &lt;/summary&gt;
        /// &lt;param name="args"&gt;
        /// <span class="code-comment">A &lt;see cref="System.String"/&gt;</span>
        /// &lt;/param&gt;</span>
        <span class="code-keyword">private static</span> <span class="code-SDKkeyword">DateTime</span> LastStatisticsOutput = DateTime.Now;

        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">Interval between PcapDevice.Statistics() output</span>
        /// &lt;/summary&gt;
        /// &lt;param name="args"&gt;
        /// <span class="code-comment">A &lt;see cref="System.String"/&gt;</span>
        /// &lt;/param&gt;</span>
        <span class="code-keyword">private static</span> <span class="code-SDKkeyword">TimeSpan</span> LastStatisticsInterval = <span class="code-keyword">new</span> <span class="code-SDKkeyword">TimeSpan</span>(<span class="code-digit">0</span>, <span class="code-digit">0</span>, <span class="code-digit">2</span>);

        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">Basic capture example</span>
        /// &lt;/summary&gt;</span>
        <span class="code-keyword">public static void</span> Main(<span class="code-keyword">string[]</span> args)
        {
            <span class="code-comment">// Print SharpPcap version</span>
            <span class="code-keyword">string</span> ver = SharpPcap.Version.VersionString;
            Console.WriteLine(<span class="code-string">&quot;SharpPcap {0}&quot;</span>, ver);

            <span class="code-comment">// If no device exists, print error</span>
            <span class="code-keyword">if</span>(CaptureDeviceList.Instance.Count &lt; <span class="code-digit">1</span>)
            {
                Console.WriteLine(<span class="code-string">&quot;No device found on this machine&quot;</span>);
                <span class="code-keyword">return</span>;
            }

            Console.WriteLine();
            Console.WriteLine(<span class="code-string">&quot;The following devices are available on this machine:&quot;</span>);
            Console.WriteLine(<span class="code-string">&quot;----------------------------------------------------&quot;</span>);
            Console.WriteLine();

            <span class="code-keyword">int</span> i=0;

            <span class="code-comment">// Print out all devices</span>
            <span class="code-keyword">foreach</span>(<span class="code-SDKkeyword">ICaptureDevice</span> dev <span class="code-keyword">in</span> CaptureDeviceList.Instance)
            {
                Console.WriteLine(<span class="code-string">&quot;{0}) {1} {2}&quot;</span>, i, dev.Name, dev.Description);
                i++;
            }

            Console.WriteLine();
            Console.Write(<span class="code-string">&quot;-- Please choose a device to capture: &quot;</span>);
            i = int.Parse(Console.ReadLine());

            <span class="code-comment">// start the background thread</span>
            <span class="code-SDKkeyword">var</span> backgroundThread = <span class="code-keyword">new</span> <span class="code-SDKkeyword">System.Threading.Thread</span>(BackgroundThread);
            backgroundThread.Start();

            <span class="code-SDKkeyword">ICaptureDevice</span> device = CaptureDeviceList.Instance[i];

            <span class="code-comment">// Register our handler function to the 'packet arrival' event</span>
            device.OnPacketArrival +=
                <span class="code-keyword">new</span> <span class="code-SDKkeyword">PacketArrivalEventHandler</span>(device_OnPacketArrival);

            <span class="code-comment">// Open the device for capturing</span>
            device.Open();

            Console.WriteLine();
            Console.WriteLine(<span class="code-string">&quot;-- Listening on {0}, hit 'Enter' to stop...&quot;</span>,
                device.Description);

            <span class="code-comment">// Start the capturing process</span>
            device.StartCapture();

            <span class="code-comment">// Wait for 'Enter' from the user. We pause here until being asked to
            // be terminated</span>
            Console.ReadLine();

            <span class="code-comment">// Stop the capturing process</span>
            device.StopCapture();

            Console.WriteLine(<span class="code-string">&quot;-- Capture stopped.&quot;</span>);

            <span class="code-comment">// ask the background thread to shut down</span>
            BackgroundThreadStop = <span class="code-keyword">true</span>;

            <span class="code-comment">// wait for the background thread to terminate</span>
            backgroundThread.Join();

            <span class="code-comment">// Print out the device statistics</span>
            Console.WriteLine(device.Statistics().ToString());

            <span class="code-comment">// Close the pcap device</span>
            device.Close();
        }

        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">Prints the time and length of each received packet</span>
        /// &lt;/summary&gt;</span>
        <span class="code-keyword">private static void</span> device_OnPacketArrival(<span class="code-SDKkeyword">object</span> sender, <span class="code-SDkkeyword">CaptureEventArgs</span> e)
        {
            <span class="code-comment">// print out periodic statistics about this device</span>
            <span class="code-SDKkeyword">var</span> Now = DateTime.Now; <span class="code-comment">// cache 'DateTime.Now' for minor reduction in cpu overhead</span>
            <span class="code-SDKkeyword">var</span> interval = Now - LastStatisticsOutput;
            <span class="code-keyword">if</span>(interval &gt; LastStatisticsInterval)
            {
                Console.WriteLine("device_OnPacketArrival: " + ((<span class="code-SDKkeyword">ICaptureDevice</span>)e.Device).Statistics());
                LastStatisticsOutput = Now;
            }

            <span class="code-comment">// lock QueueLock to prevent multiple threads accessing PacketQueue at</span>
            <span class="code-comment">// the same time</span>
            <span class="code-keyword">lock</span>(QueueLock)
            {
                PacketQueue.Add(e.Packet);
            }
        }

        <span class="code-SummaryComment">/// &lt;summary&gt;
        /// <span class="code-comment">Checks for queued packets. If any exist it locks the QueueLock, saves a</span>
        /// <span class="code-comment">reference of the current queue for itself, puts a new queue back into</span>
        /// <span class="code-comment">place into PacketQueue and unlocks QueueLock. This is a minimal amount of</span>
        /// <span class="code-comment">work done while the queue is locked.</span>
        ///
        /// <span class="code-comment">The background thread can then process queue that it saved without holding</span>
        /// <span class="code-comment">the queue lock.</span>
        /// &lt;/summary&gt;</span>
        <span class="code-keyword">private static void</span> BackgroundThread()
        {
            <span class="code-keyword">while</span>(!BackgroundThreadStop)
            {
                <span class="code-keyword">bool</span> shouldSleep = <span class="code-keyword">true</span>;

                <span class="code-keyword">lock</span>(QueueLock)
                {
                    <span class="code-keyword">if</span>(PacketQueue.Count != <span class="code-digit">0</span>)
                    {
                        shouldSleep = <span class="code-keyword">false</span>;
                    }
                }

                <span class="code-keyword">if</span>(shouldSleep)
                {
                    System.Threading.Thread.Sleep(<span class="code-digit">250</span>);
                }
                <span class="code-keyword">else</span> <span class="code-comment">// should process the queue</span>
                {
                    <span class="code-SDKkeyword">List&lt;RawCapture&gt;</span> ourQueue;
                    <span class="code-keyword">lock</span>(QueueLock)
                    {
                        <span class="code-comment">// swap queues, giving the capture callback a new one</span>
                        ourQueue = PacketQueue;
                        PacketQueue = <span class="code-keyword">new</span> <span class="code-SDKkeyword">List&lt;RawCapture&gt;</span>();
                    }

                    Console.WriteLine(<span class="code-string">&quot;BackgroundThread: ourQueue.Count is {0}&quot;</span>, ourQueue.Count);

                    <span class="code-keyword">foreach</span>(<span class="code-SDKkeyword">var</span> packet <span class="code-keyword">in</span> ourQueue)
                    {
                        <span class="code-SDKkeyword">var</span> time = packet.Timeval.Date;
                        <span class="code-SDKkeyword">var</span> len = packet.Data.Length;
                        Console.WriteLine(<span class="code-string">&quot;BackgroundThread: {0}:{1}:{2},{3} Len={4}&quot;</span>,
                            time.Hour, time.Minute, time.Second, time.Millisecond, len);
                    }

                    <span class="code-comment">// Here is where we can process our packets freely without
                    // holding off packet capture.
                    //
                    // NOTE: If the incoming packet rate is greater than
                    //       the packet processing rate these queues will grow
                    //       to enormous sizes. Packets should be dropped in these
                    //       cases
                    </span>
                }
            }
        }
    }
}
</pre>


<h2>References</h2>
<ul>
    <li><a href="http://sourceforge.net/apps/mediawiki/sharppcap/index.php">SharpPcap home page (news / getting started)</a></li>
    <li><a href="http://sourceforge.net/projects/sharppcap" target="_blank">SharpPcap SourceForge project page (File releases / source code)</a>.</li>
    <li><a href="http://www.winpcap.org/" target="_blank">WinPcap</a> - a packet capture framework for Windows.</li>
</ul>


<h2>History</h2>
<ul>
    <li>2014-May-2
        <ul>
            <li>Corrected some mistakes in the examples that users had reported in the comments section.</li>
            <li>Removed the link to www.tamirgal.com, Tamir's site appears to have gone away.</li>
            <li>Adjusted examples to reflect the change from per-packet type GetEncapculated() methods to the Packet.Extract() approach. 
        </ul>
    </li>
</ul>
<ul>
    <li>2011-Sep-13
        <ul>
            <li>Updates for new classes for reading and writing capture files, CaptureFileWriterDevice and CaptureFileReaderDevice</li>
        </ul>
    </li>
</ul>
<ul>
    <li>2011-Feb-24
        <ul>
            <li>Separate out Packet.Net packet types from description of SharpPcap</li>
            <li>Rename PacketDotNet.RawPacket to SharpPcap.RawCapture</li>
            <li>Shorten the document length</li>
        </ul>
    </li>
    <li>2011-Feb-01
        <ul>
            <li>Updated for SharpPcap v3.5 API changes</li>
        </ul>
    </li>
</ul>
<ul>
    <li>2010-Nov-07
        <ul>
            <li>Updated for SharpPcap v3.x</li>
            <li>Added queuing example for high packet rates</li>
        </ul>
    </li>
</ul>
<ul>
    <li>2010-Jan-27
        <ul>
            <li>Updated for the current version of SharpPcap, v2.4.0.</li>
        </ul>
    </li>
</ul>
<ul>
    <li>2005-Nov-27
        <ul>
            <li>Initial version posted.</li>
        </ul>
    </li>
</ul>

</body>
</html>
